﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;

using ArkanoidX.Objects;

namespace ArkanoidX.RacketStates
{
    /*
     * reusable code of helper class for controlling transition between racket states for 
     * implementing features like racket resizing and repositioning etc
     */
    public class RacketStateHelper
    {
        public Vector2 _kTargetSize;
        public Vector2 _kOriginalSize;
        public float _kOriginalY;

        public RacketStateHelper(Vector2 targetSize)
        {
            _kTargetSize = targetSize;
        }

        public void Initiate(Racket.State fadingOutState, Racket.State fadingInState)
        {
            /*
             * this transfer the related property from source state to the target as its
             * initial property
             */
            fadingInState.Size = fadingOutState.Size;
        }

        public void FadingInUpdate(Racket racket, GameTime gameTime,
            Racket.State fadingOutState, Racket.State fadingInState)
        {
            TimeSpan transtionTimePassed = gameTime.TotalGameTime - fadingInState.InitialTime;

            if (fadingInState.InnerState == Racket.State.InternalState.FadeIn)
            {
                _kOriginalSize = fadingOutState.Size;
                _kOriginalY = racket.Position.Y;
            }

            TimeSpan fadingInDuration = fadingInState.FadingInDuration;
            TimeSpan fadingOutDuration = fadingOutState.FadingOutDuration;
            TimeSpan transitionDuration;

            if (fadingInDuration < fadingOutDuration)
            {
                transitionDuration = fadingOutDuration;
            }
            else
            {
                transitionDuration = fadingInDuration;
            }

            /**
             * constrain the transition duration within the life span of the
             * state to fade in
             */
            if (transitionDuration > fadingInState.LifeSpan)
            {
                transitionDuration = fadingInState.LifeSpan;
            }

            if (transtionTimePassed < transitionDuration)
            {
                float r = (float)(transtionTimePassed.TotalMilliseconds 
                    / transitionDuration.TotalMilliseconds);

                /*
                 * let's stretch out
                 * finish within _kTransitionDuration
                 */

                fadingInState.Width = Utility.LinearInterpolate(_kOriginalSize.X, _kTargetSize.X, r);
                fadingInState.Height = Utility.LinearInterpolate(_kOriginalSize.Y, _kTargetSize.Y, r);

                if (!fadingInState.IsFree)
                {
                    /*
                     * moving to the base horizon
                     * finish within _kTransitionDuration
                     */
                    racket.Position = new Vector2(racket.Position.X,
                        Utility.LinearInterpolate(_kOriginalY, racket.BaseY, r));
                }
            }
            else
            {   /* finish transitioning */
                fadingInState.Width = _kTargetSize.X;
                fadingInState.Height = _kTargetSize.Y;

                if (!fadingInState.IsFree)
                {
                    racket.Position = new Vector2(racket.Position.X, racket.BaseY);
                }

                fadingInState.InnerState = Racket.State.InternalState.Active;
                fadingOutState.Inactivate();
            }

#if disabled_code
            Debug.WriteLine(
                string.Format("{0} to {1} ({2} to {3}({4})), {5}", _kOriginalSize.X, _kTargetSize.X,
                fadingOutState.GetType().ToString(), fadingInState.GetType().ToString(),
                fadingInState.InnerState.ToString(), fadingInState.Width));
#endif
        }
    }
}
